home *** CD-ROM | disk | FTP | other *** search
- In recognition of a number of questions I've seen recently asking
- questions on programming CD-ROMs...
-
- CD-ROM programming FAQ Version 1.00
-
- Copyright (C) 1995 by Marcus W. Johnson. All rights reserved. This
- article is not in the public domain, but it may be redistributed so
- long as this notice, the acknowledgments, and the information on
- obtaining the latest copy of this list are retained and no fee is
- charged. The code fragments may be used freely; credit would be
- polite.
-
- ------- Table of Contents --------------------------------------------
-
- Section 0 - Availability
- 0.01. How can I get the latest copy of this FAQ?
- Section 1 - MSCDEX Status
- 1.01. How do I know if MSCDEX is installed?
- 1.02. How do I determine the MSCDEX version?
- Section 2 - CD-ROM Existence
- 2.01. How many CD-ROMs are present?
- 2.02. Which drives are CD-ROMs?
- 2.03. How do I get the name of the CD-ROM device driver?
- Section 3 - Drive Interface
- 3.01. How do I open the door?
- 3.02. How do I close the door?
- 3.03. How do I unlock the door?
- 3.04. How do I lock the door?
- 3.05. How do I reset the drive?
- 3.06. How do I get drive status?
- Section 4 - Drive Capacity
- 4.01. What sector size is supported?
- 4.02. How many sectors are on the disk?
- 4.03. How much data is on the disk?
- Section 5 - Volume Table of Contents
- 5.01. How do I get the abstract file name?
- 5.02. How do I get the bibliography file name?
- 5.03. How do I get the copyright file name?
- 5.04. How do I read the Volume Table of Contents (VTOC)?
- Section 6 - Audio
- 6.01. How do I find out how many tracks are on a CD?
- 6.02. What are Red Book and HSG formats?
- 6.03. How can I determine where a particular track starts?
- 6.04. How do I play audio?
- 6.05. How do I pause audio playback?
- 6.06. How do I resume audio playback?
-
- ======================================================================
- Section 0 - Administration
- ----------------------------------------------------------------------
- 0.01. How can I get the latest copy of this FAQ?
-
- The FAQ is published monthly in comp.os.msdos.programming and
- alt.msdos.programmer.
- ----------------------------------------------------------------------
- 0.02. Where did this information come from?
-
- Ralf Brown's interrupt list
- "MS-DOS Extensions", by Ray Duncan, Microsoft Press
- My personal research for "PC-Programmer's Guide to Low-Level
- Functions and Interrupts", Sams
- The mention of particular books or programs must not be construed
- to reflect unfavorably on any that are not mentioned.
- ----------------------------------------------------------------------
- 0.03. How accurate is this information?
-
- I have personally tested the code fragments in this FAQ, and
- they appear to work as advertised, but there is no warranty on
- the code or on the techniques described in this article.
- As testing may not have been perfect, and machines and
- configurations vary, it is possible that the fragments will not
- work for you.
- Please send corrections to marcj@nando.net.
- ======================================================================
- Section 1 - MSCDEX Status
- ======================================================================
- 1.01. How do I know if MSCDEX is installed?
-
- Call the MSCDEX installation check function. Here's code that
- performs the check:
-
- mov AX,0DADAH
- push AX
- mov AX,01100H
- int 2FH
- pop BX
- cmp BX,0ADADH
- jne not_installed
- cmp AL,0FFH
- jne not_installed
- ;
- ; MSCDEX is installed
- ;
- ----------------------------------------------------------------------
- 1.02. How do I determine the MSCDEX version?
-
- Call the MSCDEX version check function. Here's code that gets
- the version:
-
- mov AX,150CH
- int 2FH
- ;
- ; BH holds the major version
- ; BL holds the minor version
- ; Prior to MSCDEX version 2.0, the version returned is 0.0 (BX =
- ; 0)
- ;
- ======================================================================
- Section 2 - CD-ROM Existence
- ======================================================================
- 2.01. How many CD-ROMs are present?
-
- Ask MSCDEX. Here's code that gives the count of CD-ROMs
- installed and the drive letter of the first one:
-
- mov AX,1500H
- xor BX,BX
- int 2FH
- ;
- ; BX will hold the number of CD-ROMs
- ; CL will hold the first CD-ROM's drive; 0 = A:, 1 = B:, and so
- ; on
- ;
-
- A problem with this method, BTW, is that it conflicts with DOS
- 4.0's GRAPHICS.COM.
- ----------------------------------------------------------------------
- 2.02. Which drives are CD-ROMs?
-
- There are two ways to find out. Both ways require MSCDEX version
- 2 (see question 1.02, How do I determine the MSCDEX version?).
- The first way gives a list of all CD-ROM drives; the second
- verifies whether a specific drive is a CD-ROM.
-
- Method 1: (get list of CD-ROMs)
- This method requires a block of memory; the size, in bytes, must
- be at least the number of drives returned by function 1500H (see
- question 2.01, How many CD-ROMs are present?).
-
- mov AX,150DH
- les BX,LetterArray
- int 2FH
- ;
- ; each byte in LetterArray will contain a drive value (0 = A:, 1
- ; = B:, etc.)
- ;
-
- Method 2: (is a specified drive a CD-ROM?)
-
- mov AX,150BH
- mov CX,Drive ; 0 = A:, 1 = B:, and so on
- int 2FH
- or AX,AX
- jz not_cd_rom
- cmp BX,0ADADH
- jne not_cd_rom
- ;
- ; the drive is a CD-ROM
- ;
- ----------------------------------------------------------------------
- 2.03. How do I get the name of the CD-ROM device driver?
-
- First, you need to know how many CD-ROMs you have (see question
- 2.01, How many CD-ROMs are present?). You need a block of memory
- whose size, in bytes, is 5 times the number of CD-ROMs present.
- This code will fill that array:
-
- mov AX,1501H
- les BX,DriverArray
- int 2FH
-
- Each 5-byte element in the array consists of the drive's subunit
- number (a CD-ROM device driver may support several drives as
- subunits), followed by the address of the drive's device driver.
- The filename is 10 bytes into the device driver. The filename is
- at most 8 bytes long, and if less than 8 bytes, is terminated by
- a space (20H).
- ======================================================================
- Section 3 - Drive Interface
- ======================================================================
- 3.01. How do I open the door?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a one byte block of
- memory. Call DOS IOCTL function 4403H, as shown here:
-
- mov BX,FileHandle
- mov Command,0
- lds DX,Command
- mov CX,1
- mov AX,4403H
- int 21H
- jc error
- cmp AX,1
- jne write_error
- ;
- ; door should be open
- ;
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
- ----------------------------------------------------------------------
- 3.02. How do I close the door?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a one byte block of
- memory. Call DOS IOCTL function 4403H, as shown here:
-
- mov BX,FileHandle
- mov Command,5
- lds DX,Command
- mov CX,1
- mov AX,4403H
- int 21H
- jc error
- cmp AX,1
- jne write_error
- ;
- ; door should be closed
- ;
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
-
- The drive should be reset after closing the door before
- accessing the drive (see question 3.05, How do I reset the
- drive?).
- ----------------------------------------------------------------------
- 3.03. How do I unlock the door?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a two-byte block of
- memory. Call DOS IOCTL function 4403H, as shown here:
-
- mov BX,FileHandle
- mov Command,1
- mov Command+1,0
- lds DX,Command
- mov CX,2
- mov AX,4403H
- int 21H
- jc error
- cmp AX,2
- jne write_error
- ;
- ; door should be unlocked
- ;
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
-
- The drive should be reset after unlocking the door before
- accessing the drive (see question 3.05, How do I reset the
- drive?).
- ----------------------------------------------------------------------
- 3.04. How do I lock the door?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a two-byte block of
- memory. Call DOS IOCTL function 4403H, as shown here:
-
- mov BX,FileHandle
- mov Command,1
- mov Command+1,1
- lds DX,Command
- mov CX,2
- mov AX,4403H
- int 21H
- jc error
- cmp AX,2
- jne write_error
- ;
- ; door should be locked
- ;
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
-
- The drive should be reset after locking the door before
- accessing the drive (see question 3.05, How do I reset the
- drive?).
- ----------------------------------------------------------------------
- 3.05. How do I reset the drive?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a one-byte block of
- memory. Call DOS IOCTL function 4403H, as shown here:
-
- mov BX,FileHandle
- mov Command,2
- lds DX,Command
- mov CX,1
- mov AX,4403H
- int 21H
- jc error
- cmp AX,1
- jne write_error
- ;
- ; drive should be reset
- ;
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
- ----------------------------------------------------------------------
- 3.06. How do I get drive status?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a five-byte block of
- memory. Call DOS IOCTL function 4402H, as shown here:
-
- mov BX,FileHandle
- mov Command,6
- lds DX,Command
- mov CX,5
- mov AX,4402H
- int 21H
- jc error
- cmp AX,5
- jne read_error
- ;
- ; The word at offset 1 of the five-byte block of memory contains
- ; status
- ; bit 10 is set if audio is playing
- ; bit 9 is set if Red Book and HSG addressing are both
- ; supported
- ; bit 8 is set if audio channel control is supported
- ; bit 7 is set if prefetch requests are supported
- ; bit 5 is set if interleaving is supported
- ; bit 4 is set if audio/video track playback is supported
- ; bit 3 is set if the CD-ROM is writable
- ; bit 2 is set if raw and cooked read is supported
- ; bit 1 is set if the door is unlocked
- ; bit 0 is set if the door is open
- ;
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
-
- The drive should be reset after checking drive status before
- accessing the drive (see question 3.05, How do I reset the
- drive?).
- ======================================================================
- Section 4 - Drive Capacity
- ======================================================================
- 4.01. What sector size is supported?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a four-byte block of
- memory. Call DOS IOCTL function 4402H, as shown here:
-
- mov BX,FileHandle
- mov Command,7
- lds DX,Command
- mov CX,4
- mov AX,4402H
- int 21H
- jc error
- cmp AX,4
- jne read_error
- ;
- ; The byte at offset 1 of the four-byte block of memory contains
- ; raw/cooked status (0 = cooked, 1 = raw)
- ; The word at offset 2 of the four-byte block of memory contains
- ; the sector size
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
-
- The drive should be reset after getting the sector size before
- accessing the drive (see question 3.05, How do I reset the
- drive?).
- ----------------------------------------------------------------------
- 4.02. How many sectors are on the disk?
-
- First, you need the name of the device driver (see question 2.03,
- How do I get the name of the CD-ROM device driver?). Open the
- file for read/write and obtain the file handle (DOS function 3DH
- will suffice).
-
- Once you have the file handle, you need a five-byte block of
- memory. Call DOS IOCTL function 4402H, as shown here:
-
- mov BX,FileHandle
- mov Command,8
- lds DX,Command
- mov CX,5
- mov AX,4402H
- int 21H
- jc error
- cmp AX,5
- jne read_error
- ;
- ; The dword at offset 1 of the five-byte block of memory
- ; contains the number of sectors
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
-
- The drive should be reset after getting the number of sectors
- before accessing the drive (see question 3.05, How do I reset
- the drive?).
- ----------------------------------------------------------------------
- 4.03. How much data is on the disk?
-
- See question 4.01, What sector size is supported?, and question
- 4.02, How many sectors are on the disk?. Take the product of the
- two values returned. The conventional DOS functions don't work
- reliably.
- ======================================================================
- Section 5 - Volume Table of Contents
- ======================================================================
- 5.01. How do I get the abstract file name?
-
- You need a 38-byte block of memory to hold the abstract file
- name. This code will fill that block:
-
- les BX,Buffer
- mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
- mov AX,1503H
- int 2FH
- jc error
- ;
- ; buffer is filled with the abstract file name.
- ;
-
- The file name is nul-terminated.
-
- The drive should be reset after getting the abstract file name
- before accessing the drive (see question 3.05, How do I reset
- the drive?).
- ----------------------------------------------------------------------
- 5.02. How do I get the bibliography file name?
-
- You need a 38-byte block of memory to hold the bibliography file
- name. This code will fill that block:
-
- les BX,Buffer
- mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
- mov AX,1504H
- int 2FH
- jc error
- ;
- ; buffer is filled with the bibliography file name.
- ;
-
- The file name is nul-terminated.
-
- The drive should be reset after getting the bibliography file
- name before accessing the drive (see question 3.05, How do I
- reset the drive?).
- ----------------------------------------------------------------------
- 5.03. How do I get the copyright file name?
-
- You need a 38-byte block of memory to hold the copyright file
- name. This code will fill that block:
-
- les BX,Buffer
- mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
- mov AX,1502H
- int 2FH
- jc error
- ;
- ; buffer is filled with the copyright file name.
- ;
-
- The file name is nul-terminated.
-
- The drive should be reset after getting the copyright file name
- before accessing the drive (see question 3.05, How do I reset
- the drive?).
- ----------------------------------------------------------------------
- 5.04. How do I read the Volume Table of Contents (VTOC)?
-
- The VTOC is read in 2048-byte blocks. This code fills a VTOC
- block:
-
- les BX,Buffer
- mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
- mov DX,BlockNumber ; 0 for the first block
- mov AX,1505H
- int 2FH
- jc error
- ;
- ; block is filled
- ;
- ; AX contains the descriptor type for this block:
- ; 0001H = standard volume descriptor
- ; 00FFH = volume descriptor terminator
- ;
-
- On error, AX will hold an error value: 000FH (invalid drive) or
- 0015H (drive not ready).
- ======================================================================
- Section 6 - Audio
- ======================================================================
- 6.01. How do I find out how many tracks are on a CD?
-
- First, you need the name of the device driver (see question
- 2.03, How do I get the name of the CD-ROM device driver?). Open
- the file for read/write and obtain the file handle (DOS function
- 3DH will suffice).
-
- Once you have the file handle, you need a seven-byte block of
- memory. Call DOS IOCTL function 4402H, as shown here:
-
- mov BX,FileHandle
- mov Command,0AH
- lds DX,Command
- mov CX,7
- mov AX,4402H
- int 21H
- jc error
- cmp AX,7
- jne read_error
- ;
- ; The byte at offset 1 of the seven-byte block of memory is the
- ; number of the first track
- ; The byte at offset 2 of the seven-byte block of memory is the
- ; number of the last track
- ; The dword at offset 4 of the seven-byte block of memory is the
- ; start address of the first track in Red Book format
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
- ----------------------------------------------------------------------
- 6.02. What are Red Book and HSG formats?
-
- Both are ways of encoding frame information. An audio frame is
- 1/75 second of audio. HSG encodes frame information into a
- double word: minute multiplied by 4500, plus second multiplied
- by 75, plus frame, minus 150. Red Book encodes frame information
- into a four-byte data structure:
- Byte 0: frame number
- Byte 1: second
- Byte 2: minute
- Byte 3: unused
- ----------------------------------------------------------------------
- 6.03. How can I determine where a particular track starts?
-
- First, you need the name of the device driver (see question
- 2.03, How do I get the name of the CD-ROM device driver?). Open
- the file for read/write and obtain the file handle (DOS function
- 3DH will suffice).
-
- Once you have the file handle, you need an eight-byte block of
- memory. Call DOS IOCTL function 4402H, as shown here:
-
- mov BX,FileHandle
- mov Command,0BH
- mov Command+1,TrackNumber
- lds DX,Command
- mov CX,8
- mov AX,4402H
- int 21H
- jc error
- cmp AX,8
- jne read_error
- ;
- ; The dword at offset 2 of the eight-byte block of memory is the
- ; start address of the specified track in Red Book format
- ; The word at offset 6 of the eight-byte block of memory is the
- ; track control information. Bits 15-12 are used:
- ; 0xxx: Two audio channels, no pre-emphasis, digital copy not
- ; permitted
- ; 1xxx: Two audio channels, with pre-emphasis, digital copy not
- ; permitted
- ; 2xxx: Two audio channels, no pre-emphasis, digital copy
- ; permitted
- ; 3xxx: Two audio channels, with pre-emphasis, digital copy
- ; permitted
- ; 4xxx: Data track, digital copy not permitted
- ; 6xxx: Data track, digital copy permitted
- ; 8xxx: Four audio channels, no pre-emphasis, digital copy not
- ; permitted
- ; 9xxx: Four audio channels, with pre-emphasis, digital copy not
- ; permitted
- ; Axxx: Four audio channels, no pre-emphasis, digital copy
- ; permitted
- ; Bxxx: Four audio channels, with pre-emphasis, digital copy
- ; permitted
-
- On error (carry set), AX will hold an error code: 0001H (invalid
- function), 0005H (access denied), 0006H (invalid handle), or
- 000DH (invalid data).
- ----------------------------------------------------------------------
- 6.04. How do I play audio?
-
- For starters, you need MSCDEX Version 2.1 or greater (see
- question 1.02, How do I determine the MSCDEX version?).
-
- You also need the subunit number for the drive containing the
- audio CD (see question 2.03, How do I get the name of the CD-ROM
- device driver?)
-
- You also need to know what frame you want to start with (see
- question 6.03, How can I determine where a particular track
- starts?), and how many frames you want to play.
-
- Now, you need a 22-byte block of memory. Write 22 (16H) to the
- first byte. Write the subunit number to the second byte. Write
- 84H to the third byte. Write 0 to the byte at offset 0DH (this
- sets up HSG addressing). Convert the starting frame number to
- HSG format and write the 4-byte result to the dword at offset
- 0EH. Finally, write the frame count to the dword at offset 12H.
-
- To play the CD as instructed, execute this code:
-
- les BX,Buffer
- mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
- mov AX,1510H
- int 2FH
- ;
- ; status is in the word at offset 3 of the buffer. Look for bit
- ; 8 set (done), and watch out for bit 15 set (error).
- ;
- ----------------------------------------------------------------------
- 6.05. How do I pause audio playback?
-
- For starters, you need MSCDEX Version 2.1 or greater (see
- question 1.02, How do I determine the MSCDEX version?).
-
- You also need the subunit number for the drive containing the
- audio CD (see question 2.03, How do I get the name of the CD-ROM
- device driver?)
-
- Now, you need a 13-byte block of memory. Write 13 (0DH) to the
- first byte. Write the subunit number to the second byte. Write
- 85H to the third byte.
-
- To pause the CD, execute this code:
-
- les BX,Buffer
- mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
- mov AX,1510H
- int 2FH
- ;
- ; status is in the word at offset 3 of the buffer. Look for bit
- ; 8 set (done), and watch out for bit 15 set (error).
- ;
- ----------------------------------------------------------------------
- 6.06. How do I resume audio playback?
-
- For starters, you need MSCDEX Version 2.1 or greater (see
- question 1.02, How do I determine the MSCDEX version?).
-
- You also need the subunit number for the drive containing the
- audio CD (see question 2.03, How do I get the name of the CD-ROM
- device driver?)
-
- Now, you need a 13-byte block of memory. Write 13 (0DH) to the
- first byte. Write the subunit number to the second byte. Write
- 88H to the third byte.
-
- To resume, execute this code:
-
- les BX,Buffer
- mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
- mov AX,1510H
- int 2FH
- ;
- ; status is in the word at offset 3 of the buffer. Look for bit
- ; 8 set (done), and watch out for bit 15 set (error).
- ;
-
-
-
-